# -*- coding: utf-8 -*-
#
# fusion.tracker.Tracker
#
# Copyright 2007 Helsinki Institute for Information Technology
# and the authors.
#
# Authors: Toni Ruottu <toni.ruottu@iki.fi>
#          Harri Hämäläinen <harri.hamalainen@helsinki.fi>

# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

'''
Handle URLs of the form "/tracker/([0-9a-f]{40})/(.*)".
'''

import web
from fusion.http.util import withdb
from fusion.db.exceptions import *
from fusion.db.db import bytes_to_hex, hex_to_bytes
from fusion.tracker.pybencode import PyBencode
from fusion.tracker.Tracker_collection import Tracker_collection

class Tracker(Tracker_collection):

    def __init__(self):
        Tracker_collection.__init__(self, None)

    @withdb
    def GET(self, db, collection, request=''):

        input = web.input(output='', timeout='')

        timeout = None
        block = True
        
        if input.timeout:
            try:
                timeout = float(input.timeout)
                block = (timeout > 0)
            except ValueError:
                return web.badrequest()

        try:
            db.keys(collection,
                    autoimport = True,
                    block = block,
                    timeout = timeout)
        except NoSuchCollection:
            return web.notfound()

        self.collection = collection

        if request == 'announce':
            self.announce()

        if request == 'scrape':
            self.scrape()

        return

    def peers_to_announce(self):

        input = web.input(ip='', peer_id='', port='',)

        peer = {}

        for k, v in input.items():
            if k in ['ip','port','uploaded','downloaded','left']:
                peer[k] = v

        peer['timestamp'] = self.stamp_now()

        ip=peer['ip']
        if not ip:
            ip = web.ctx.ip
            if ip[:3] == '127':
                peer['ips'] = web.config.sync_daemon.get_my_ip_addresses()
            peer['ip']=ip

        peer_id = input['peer_id']

        mypeers = {}
        mypeers[peer_id] = peer

        return mypeers


    @withdb
    def announce(self, db):

        input = web.input(info_hash='',event='',numwant=50)
        info_hash = input.info_hash
        
        if bytes_to_hex(info_hash) not in self.published(db):
            error = {}
            error['failure reason'] = 'Your torrent (info_hash='+bytes_to_hex(info_hash)+') has not been approved by tracker administrator.'
            web.output(PyBencode().encode(error))
            return

        numwant = input.numwant

        if input.event == 'completed':
            self.download_complete(db,info_hash)

        if input.event == 'stopped':
            self.clear_advertisements(db,info_hash)
        else:
            mynewpeers = self.peers_to_announce()
            self.advertise(db,info_hash,mynewpeers)

        peers = self.discover(db,info_hash)
        web.output(self.tracker_response(peers,numwant))

        return

    @withdb
    def scrape(self, db):
        requested = set(web.input(info_hash=[]).info_hash)
        published = set([hex_to_bytes(p) for p in self.published(db)])

        if requested:
            requested = requested & published
        else:
            requested = published

        files = {}

        for info_hash in requested:

            file_info = {}

            peers = self.discover(db,info_hash)
            complete = self.count_seeds(peers)

            file_info['complete'] = complete
            file_info['incomplete'] = len(peers) - complete

            file_info['downloaded'] = self.count_completed(db, info_hash)
            files[info_hash] = file_info

        response = {}
        response['files'] = files

        ben = PyBencode().encode(response)

        web.output(ben)

        return
